Apache Ant

 

User/system requirements

  • You will need some knowledge of XML.
  • Ant needs to know where java is located and must be in the classpath.  If you haven’t done so, you’ll need to set JAVA_HOME in control panel/system/advanced/environment variables. See info below.

 

What are we after?  At the 200-level a “project” might consist of two to five class files in the same package.  With multi-tiered web application development, there may be dozens of files spread across many directories, including resources like images and css, views like html, java and flex classes, and configurations files.  Some resources or dependencies may be remote.  The server may be remote.  We want to simplify and make consistent the build process, even if the directory structure is complicated and there are many files.

  • This includes class path settings for compile and run
  • May include testing, documentation generation (javadoc)
  • May include deploy/undeploy to a server for web apps

 

 

http://ant.apache.org/

The manual is located at

http://ant.apache.org/manual/index.html

 

Includes these install instructions

Installing Ant

The binary distribution of Ant consists of the following directory layout:

  ant
   +--- README, LICENSE, fetch.xml, other text files. //basic information
   +--- bin  // contains launcher scripts
   |
   +--- lib  // contains Ant jars plus necessary dependencies
   |
   +--- docs // contains documentation
   |      |
   |      +--- images  // various logos for html documentation
   |      |
   |      +--- manual  // Ant documentation (a must read ;-)
   |
   +--- etc // contains xsl goodies to:
            //   - create an enhanced report from xml output of various tasks.
            //   - migrate your build files and get rid of 'deprecated' warning
            //   - ... and more ;-)

Only the bin and lib directories are required to run Ant. To install Ant, choose a directory and copy the distribution files there. This directory will be known as ANT_HOME.

Windows 95, Windows 98 & Windows ME Note:

 

On these systems, the script used to launch Ant will have problems if ANT_HOME is a long filename (i.e. a filename which is not of the format known as "8.3"). This is due to limitations in the OS's handling of the "for" batch-file statement. It is recommended, therefore, that Ant be installed in a short, 8.3 path, such as C:\Ant.

 

On these systems you will also need to configure more environment space to cater for the environment variables used in the Ant lauch script. To do this, you will need to add or update the following line in the config.sys file

shell=c:\command.com c:\ /p /e:32768

Setup

Before you can run Ant there is some additional set up you will need to do unless you are installing the RPM version from jpackage.org:

  • Add the bin directory to your path.
  • Set the ANT_HOME environment variable to the directory where you installed Ant. On some operating systems, Ant's startup scripts can guess ANT_HOME (Unix dialects and Windows NT/2000), but it is better to not rely on this behavior.
  • Optionally, set the JAVA_HOME environment variable (see the Advanced section below). This should be set to the directory where your JDK is installed.

Note: Do not install Ant's ant.jar file into the lib/ext directory of the JDK/JRE. Ant is an application, whilst the extension directory is intended for JDK extensions. In particular there are security restrictions on the classes which may be loaded by an extension.

Windows Note:

 

The ant.bat script makes use of three environment variables - ANT_HOME, CLASSPATH and JAVA_HOME. Ensure that ANT_HOME and JAVA_HOME variables are set, and that they do not have quotes (either ' or ") and they do not end with \ or with /. CLASSPATH should be unset or empty.

Check Installation

You can check the basic installation with opening a new shell and typing ant. You should get a message like this

Buildfile: build.xml does not exist!
Build failed

So Ant works. This message is there because you need to write an individual buildfile for your project. With a ant -version you should get an output like

Apache Ant version 1.7.0 compiled on December 13 2006

Optional Tasks

Ant supports a number of optional tasks. An optional task is a task which typically requires an external library to function. The optional tasks are packaged together with the core Ant tasks.

The external libraries required by each of the optional tasks is detailed in the Library Dependencies section. These external libraries must be added to Ant's classpath, in any of the following ways:

·         In ANT_HOME/lib. This makes the JAR files available to all Ant users and builds.

·         In ${user.home}/.ant/lib (as of Ant 1.6). This allows different users to add new libraries to Ant. All JAR files added to this directory are available to command-line Ant.

·         On the command line with a -lib parameter. This lets you add new JAR files on a case-by-case basis.

·         In the CLASSPATH environment variable. Avoid this; it makes the JAR files visible to all Java applications, and causes no end of support calls. See below for details.

·         In some <classpath> accepted by the task itself. For example, as of Ant 1.7.0 you can run the <junit> task without junit.jar in Ant's own classpath, so long as it is included (along with your program and tests) in the classpath passed when running the task.

Where possible, this option is generally to be preferred, as the Ant script itself can determine the best path to load the library from: via relative path from the basedir (if you keep the library under version control with your project), according to Ant properties, environment variables, Ivy downloads, whatever you like.

IDEs have different ways of adding external JAR files and third-party tasks to Ant. Usually it is done by some configuration dialog. Sometimes JAR files added to a project are automatically added to ant's classpath.

The CLASSPATH environment variable

The CLASSPATH environment variable is a source of many Ant support queries. As the round trip time for diagnosis on the Ant user mailing list can be slow, and because filing bug reports complaining about 'ant.bat' not working will be rejected by the developers as WORKSFORME "this is a configuration problem, not a bug", you can save yourself a lot of time and frustration by following some simple steps.

  1. Do not ever set CLASSPATH. Ant does not need it, it only causes confusion and breaks things.
  2. If you ignore the previous rule, do not ever, ever, put quotes in the CLASSPATH, even if there is a space in a directory. This will break Ant, and it is not needed.
  3. If you ignore the first rule, do not ever, ever, have a trailing backslash in a CLASSPATH, as it breaks Ant's ability to quote the string. Again, this is not needed for the correct operation of the CLASSPATH environment variable, even if a DOS directory is to be added to the path.
  4. You can stop Ant using the CLASSPATH environment variable by setting the -noclasspath option on the command line. This is an easy way to test for classpath-related problems.

The usual symptom of CLASSPATH problems is that ant will not run with some error about not being able to find org.apache.tools.ant.launch.Launcher, or, if you have got the quotes/backslashes wrong, some very weird Java startup error. To see if this is the case, run ant -noclasspath or unset the CLASSPATH environment variable.

You can also make your Ant script reject this environment variable just by placing the following at the top of the script (or in an init target):

<property environment="env."/>
<property name="env.CLASSPATH" value=""/>
<fail message="Unset $CLASSPATH / %CLASSPATH% before running Ant!">
    <condition>
        <not>
            <equals arg1="${env.CLASSPATH}" arg2=""/>
        </not>
    </condition>
</fail>

 

 

Many tutorials are available on the web. You should work through one or more simple java build processes with ant before undertaking more complicated builds.

 

Tutorial#0:

This is from

http://supportweb.cs.bham.ac.uk/docs/tutorials/docsystem/build/tutorials/ant/ant.html

I substituted another image file for the one referenced in this article.

1.Introduction

Imagine that you are working on a large project. The project is a Java project and consists of many .java files. It consists of classes that are dependent on other classes and classes which are stubs or drivers, they are situated in multiple directories and the output files must go into multiple directories too, you have various project build routes for different applications and at the moment are coordinating all of this manually or using some other build utility which doesn't do what you want it to so many hours are spent changing directories compiling individual files and so on... Now, imagine if their was a tool that could alleviate the stress and hassle you are experiencing, OK, enough of the rhetoric, this tool exists, it is called ANT. For a nice definition of what Ant is, see http://jakarta.apache.org/ant/.

Ant (originally an acronym for Another Neat Tool), is a build tool with special support for the Java programming language but can be used for just about everything. Ant is platform-independent; it is written purely in Java. Ant is particularly good at automating complicated repetitive tasks and thus is well suited for automating standardised build processes. Ant accepts instructions in the form of XML documents thus is extensible and easy to maintain.

2.Ant Installation

The documentation for the installation is written under the assumption that the reader has some experience of installing software on computers and knows how to change the operating environment of the particular operating system they are using. The documents entitled Configuring A Windows Working Environment and Configuring A Unix Working Environment are of use to people who need to know more.

  1. Download the binaries from http://jakarta.apache.org/ant/index.html, unzip them to a suitable directory.
  2. Append /path/to/ant/bin to the PATH environment variable.
  3. Append the .jar files in /path/to/ant/lib/ to the CLASSPATH environment variable. Set JAVA_HOME to point to the location of the JDK installation on the machine that the software is being installed on. Append /path/to/jdk/lib/* to the CLASSPATH environment variable.

The installation instructions provided with the Ant software installation download are clear enough to warrant abstaining from writing any more about the installation here. Refer to /path/to/ant/docs/manual/install.html.

3.Ant Basics

An Ant build file comes in the form of an XML document, all that is required is a simple text editor to edit the build file(s). An editor that provides XML syntax highlighting is preferable. The Ant installation comes with a JAXP-Compliant XML parser, this means that the installation of an external XML parser is not necessary.

A simple Ant example is shown below followed by a set of instructions indicating how to use Ant. It is recommended that the reader follow these instructions to gain some experience in using Ant.

Example1.Basic build.xml Example

<?xml version="1.0"?> 1

<project name="test" default="compile" basedir="."> 2

 

     <property name="src" value="."/> 3

     <property name="build" value="build"/>

 

     <target name="init">  4

          <mkdir dir="${build}"/>

     </target>

 

     <target name="compile" depends="init"> 5

          <!-- Compile the java code -->

         

          <javac srcdir="${src}" destdir="${build}"/> 6

     </target>

</project>

1

<?xml version="1.0"?>

Since Ant build files are XML files the document begins with an XML declaration which specifies which version of XML is in use, this is to allow for the possibility of automatic version recognition should it become necessary.

2

<project name="test" default="compile" basedir=".">

The root element of an Ant build file is the project element, it has three attributes.

  • name: The name of the project, it can be any combination of alphanumeric characters that constitute valid XML.
  • default: The default target to use when no target is specified, out of these three attributes default is the only required attribute.
  • basedir: The base directory from which any relative directories used within the Ant build file are referenced from. If this is omitted the parent directory of the build file will be used.

3

<property name="src" value="."/>

<property name="build" value="build"/>

The property element allows the declaration of properties which are like user-definable variables available for use within an Ant build file. The name attribute specifies the name of the property and the value attribute specifies the desired value of the property. The name and value values are subject to standard XML constraints. In the markup shown above src has been assigned the value ".".

In order to reference a property defined in this manner one specifies the name between ${ and }, for example, to reference the value of src one uses ${ src }. In the example, src is used later on to specify the location of the .java files to be processed.

4

<target name="init">

     <mkdir dir="${build}"/>

</target>

The target element is used as a wrapper for a sequences of actions. A target has a name, so that it can be referenced from elsewhere, either externally from the command line, or internally via the depends keyword, or through a direct call. The target in the example is called "init" (initiate), it makes a directory using the mkdir element with the name specified by the build property defined in three.

The target element has a number of possible attributes, unless otherwise specified, these are optional:

  • name: The name of the target is used to reference it from elsewhere, it is subject to the constraints of XML well formed-ness. This is the only required attribute for the target element.
  • depends: This is a comma separated list of all the targets on which this target depends, for example, number 5 illustrates how compile depends on init, in other words, depends contains the list of the targets that must be executed prior to executing this target.
  • if: This is a useful attribute which allows one to add a conditional attribute to a target based on the value of a property , for example, if="gui-ready" could be used to only execute the encapsulating target's instructions if the property gui-ready was is (to any value).
  • unless: This is the converse of if, for example, unless="gui-ready" could be used to conditionally execute the contents of the encapsulating target. The targets' contents will be executed unless the the property gui-ready is set (to any value).
  • description: This is a short description of the target.

5

<target name="compile" depends="init">

     <!-- Compile the java code -->

    

     <javac srcdir="${src}" destdir="${build}"/>

</target>

As explained in four, depends allows one to specify other targets that must be executed prior to the execution of this target. In the listing above depends="init" is used to indicate that the compile target requires that the target named init be executed prior to executing the body of compile.

6

<target name="compile" depends="init">

     <!-- Compile the java code -->

    

     <javac srcdir="${src}" destdir="${build}"/>

</target>

The javac element, as used above, is a task, tasks are performed in the body of a target, in this case, the source directory is specified by referencing the src property and the destination directory is specified by referencing the build property. The example above causes javac to be executed, compiling all the .java files in the directory specified by the src property and placing the resultant .class files in the directory specified by the build property.

Copy the source code in the example into a text editor and save the file as build.xml. Create a test directory and place the file in it. Create some arbitrary .java file and place it in the same directory as build.xml. For convenience, here is an example .java file: test.java. Place the java file in the same directory as build.xml.

public class test {

   public static void main(String[] args) {

      System.out.println("Hello World!");

   }

}

Type the following at the commandline in the test directory:

ant -v

This will create a directory called build, compile test.java and place the .class file created in the build directory. The -v directs ant to be verbose. This verbosity causes the command to echo lots of information, information that is not really necessary for most normal purposes. Execute the command sequence again. An example output message is shown below:

[javac] test.java omitted as /path/to/temp/build/test.class is up todate

A nice feature of Ant is that by default, only those .java input files that have a more recent timestamp than their corresponding .class output files will be compiled.

4.A Typical Project

This section intends to provide and describe a typical Ant buildfile, such that, the example given could be easily modified to suit ones personal needs.

When starting a project it is a good idea to follow the suggestion in the Ant documentation of using three directories:

  1. src : For project source files.
  2. build : For compiled/output files produced (by Ant).
  3. lib : For class libraries and dependency files.

Create a test directory and from within this, create the three directories described above.

A simple Java program will be used to illustrate the use of Ant. Copy the following program into a file called UKLights.java and place it in the src directory:

import javax.swing.*;

import java.awt.*;

public class UKLights extends JFrame {

 

   public UKLights() {

      super("UKLights");

      ImageIcon icon = new ImageIcon("uklights.jpeg");

      getContentPane().add(new JLabel(icon));

      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

      setSize(new Dimension(315,244));

      setVisible(true);

   }

 

 

   public static void main(String args[]) {

      new UKLights();

   }

}

Alternatively, download the file from here: UKLights.java. The program imports the auxilliary Java classes and defines two methods. The first method is the constructor for the class which extends JFrame. The constructor calls super to initiate a JFrame with the title "UKLights". An ImageIcon is created containing the image uklights.jpeg. uklights.jpeg can be downloaded here: uklights.jpeg.

Readers of the print version of this tutorial should use some other jpeg or gif and make the necessary adjustments to the program source. After the ImageIcon is created it is added to a new JLabel which is then added to the JFrame. The default close operation for the JFrame is set, the size set to that of the ImageIcon, and the frame made visible. The second method is the main method which is called when executing the program like this:

java UKLights

The program displays the specified image in a JFrame. Change into the base directory that the directories src, build, and lib were created from. Create a file called build.xml.

The first thing that the build file must contain is a standard XML declaration:

<?xml version="1.0"?>

This provides a way for any tools that may process the file to find out the version of XML in use. Next, add the standard Ant root XML element, project:

<project name="UKLights" default="all" basedir=".">

</project>

The rest of the Ant buildfile is contained within this element. Three attributes have been specified for the project. The first is name; the name given to this project. The second is default; the default target to build, in this case all. The third is basedir which specifies the directory to use as the base directory, in this case, the current directory is used as indicated by '.'. The base directory is relative to the build file.

The rest of the code snippets in this section shouold be placed inside the project element in the sequence in which they are introduced. Add these property definitions:

<property name="src"   value="src"/>

  <property name="build" value="build"/>

  <property name="lib"   value="lib"/>

These property definitions define properties of which the values can be accessed within the buildfile by enclosing the property name within braces and prefixing it with a dollar sign. To reference the property src use ${src}. In this example, properties specifying the location of the source, build, and library directories described earlier have been created. This may seem unnecessary since, in this case, it takes longer to reference the property names than to type the actual values. However, referencing these directories via properties allows one to change the locations of these directories without having to change every reference to them. If Ant is ran on this buildfile the following error message is produced:

Buildfile: build.xml

BUILD FAILED

Target `all' does not exist in this project.

 

Total time: 1 second

   

This specifies that the target all has not been defined yet, add it:

<target name="all" depends="UKLights"

           description="Builds the whole project">

  <echo>Doing all</echo>

</target>

The all target depends on the target "UKLights", meaning that "UKLights" will be called prior to executing the body of all. The description defined will be used by Ant's projecthelp option. Add the "UKLights" target that all depends on:

<target name="UKLights"

               description="Builds the main UKLights project">

  <echo>Doing UKLights</echo>

</target>

This target has a name and a description. The target descriptions are used by Ant's projecthelp option to display information about the available targets. If one executes the following command sequence:

ant -projecthelp

The output produced is:

Buildfile: build.xml

Main targets:

 

 UKLights  Builds the main UKLights project

 all       Builds the whole project

 

Default target: all

   

One executes the build file by typing ant in the base directory, the output produced is:

Buildfile: build.xml

 

UKLights:

     [echo] Doing UKLights

 

all:

     [echo] Doing all

 

BUILD SUCCESSFUL

Total time: 1 second

   

Notice that "UKLights" was called before "all" because "all" depended on it. Both targets have simple tasks, they both echo a message to the screen indicating that they have been called. The target should compile the Java file so add the line:

<javac srcdir="${src}" destdir="${build}"/>

Ant has built in support for the Java oriented commands java and javac. The javac element compiles all the java files in the directory specified by the srcdir attribute and places them in the directory specified by the destdir attribute. Ant will only compile those source files with more recent timestamps than their corresponding output .class files. This behaviour is present in certain other Ant tasks, where it is not present, one must add the desired functionality manually. The output produced when Ant is ran on the modified build file is shown below:

Buildfile: build.xml

 

UKLights:

     [echo] Doing UKLights

    [javac] Compiling 1 source file to \blah\blah\blah\build

 

all:

     [echo] Doing all

 

BUILD SUCCESSFUL

Total time: 2 seconds

   

There are various options that may be supplied to the javac task by setting their respective attributes in the task call. Options available include, listfiles - to list the files to be compiled, failonerror - to cause the build to fail if compilation errors are encountered, and verbose to specify that java be verbose. To set an attribute, set it's value to "true". If ant is ran on the buildfile again without modifying anything it produces the output:

Buildfile: build.xml

 

UKLights:

     [echo] Doing UKLights

 

all:

     [echo] Doing all

 

BUILD SUCCESSFUL

Total time: 1 second

   

Which illustrates that no compilation was done this time round. Change into the build directory and execute UKLights.class. No picture is available because it was not copied into the build directory, add this line before the javac task:

<copy file="${src}/UKLights.jpeg" tofile="${build}/UKLights.jpeg"/>

Running ant on the modified build file produces identical output to last time with the addition of the line:

[copy] Copying 1 file to C:\docbook\docproj\src\items\ant\files\build

By default, Ant will only copy the file if it is more recent than the target file or the target file does not exist. To override this behaviour so that Ant always copies the file(s) specified, set the overwrite attribute to "true".

Another source file will be added to the program. Change the constructor of UKLights.java to:

public UKLights() {

   super("UKLights");

   ImageIcon icon = new ImageIcon("uklights.jpeg");

 

   JButton exitButton = new JButton("Exit");

   exitButton.addActionListener(new ExitControl());

 

   JButton aboutButton = new JButton("About");

   aboutButton.addActionListener(new AboutControl());

 

   getContentPane().setLayout(new FlowLayout());

   getContentPane().add(new JLabel(icon));

   getContentPane().add(aboutButton);

   getContentPane().add(exitButton);

 

   setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

   setSize(new Dimension(315,294));

   setVisible(true);

}

An exit button has been added and an about button, the layout has been set to FlowLayout, and the size of the JFrameincreased to accommodate the buttons. The ExitControl to handle events from exitButton:

import java.awt.event.*;

public class ExitControl implements ActionListener {

   public void actionPerformed(ActionEvent e) {

      System.exit(0);

   }

}

Save this in a file called ExitControl.java, or download it here: ExitControl.java. Put the file in the src directory. ExitControl causes the program to terminate when the user clicks on the exit button. An about button is created to display information about the picture loaded, events from this button are handled by AboutControl:

import java.awt.event.*;

public class AboutControl implements ActionListener {

   public void actionPerformed(ActionEvent e) {

      new AboutPopup();

   }

}

Save this in a file called AboutControl.java, or download it here: AboutControl.java. Put the file in the src directory. AboutControl.java creates a new AboutPopup:

import javax.swing.*;

import java.awt.*;

public class AboutPopup extends JFrame {

   public AboutPopup() {

      super("About");

      String message = "\n";

      message+="This image of Earth's city lights was created with data ";

      message+="from the Defense Meteorological Satellite Program ";

      message+="(DMSP) Operational Linescan System (OLS). ";

      message+="Originally designed to view clouds by moonlight, ";

      message+="the OLS is also used to map the locations of permanent ";

      message+="lights on the Earth's surface.\n\n";

      message+="The image has been modified by Ashley Mills to only include ";

      message+="the UK, the original image and further description can be ";

      message+="found at:\n\n";

      message+="http://visibleearth.nasa.gov/cgi-bin/viewrecord?5826\n\n";

      message+="This is also where the description was taken from.";

      setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

      setSize(new Dimension(315,294));

      JTextPane messagePane = new JTextPane();

      messagePane.setBackground(Color.BLACK);

      messagePane.setForeground(Color.GRAY);

      messagePane.setEditable(false);

      messagePane.setText(message);

      getContentPane().add(messagePane);

      setResizable(false);

      setVisible(true);

   }

}

Save this in a file called AboutPopup.java or download it here: AboutPopup.java. Put the file in the src directory. AboutPopup.java extends JFrame hence when instantiated will create a new frame so super is called with the string that will be the title of the JFrame. A message is defined. The default close operation for the JFrame is set. The size of the JFrameis set. A JTextPane is created, it's colours are setup and it's is made non-editable. It's message is set. It is added to the JFrame. The JFrame is made non-resizable and made visible.

Modify the "UKLights" target in build.xml:

<target name="UKLights" depends="AboutControl,ExitControl"

          description="Builds the main UKLights project">

  <echo>Doing UKLights</echo>

  <copy file="${src}/UKLights.jpeg" tofile="${build}/UKLights.jpeg"/>

  <javac srcdir="${src}" destdir="${build}" includes="UKLights.java"/>

</target>

The "UKLights" target now depends on the "AboutControl" and "ExitControl" targets. The javac line has been modified so that only UKLights.java is compiled by this target, the includes attribute, which can accept a list of files, is used to acheive this. Usually one would just use a single javac task to compile all the classes by ommiting the includes attribute. Add the AboutControl target:

<target name="AboutControl" depends="AboutPopup"

          description="Builds AboutControl">

  <echo>Doing AboutControl</echo>

  <javac srcdir="${src}" destdir="${build}" includes="AboutControl.java"/>

</target>

This compiles AboutControl.java and depends on the "AboutPopup" target. Add the "AboutPopup" target:

<target name="AboutPopup" description="Builds AboutPopup">

  <echo>Doing AboutPopup</echo>

  <javac srcdir="${src}" destdir="${build}" includes="AboutPopup.java"/>

</target>

This compiles AboutPopup.java. Add the "ExitControl" target:

<target name="ExitControl" description="Builds ExitControl">

  <echo>Doing ExitControl</echo>

  <javac srcdir="${src}" destdir="${build}" includes="ExitControl.java"/>

</target>

This compiles ExitControl.java. One more target, "Clean", will be added. "Clean"'s purpose is to delete the contents of the build directory.

<target name="Clean" description="Removes previous build">

  <delete verbose="true">

    <fileset dir="${build}"/>

  </delete>

</target>

This deletes the contents of the build directory, this is achieved by specifying a fileset with the dir attribute set to the directory to delete the contents of. To delete the directory as well as the contents of the directory, set theincludeEmptyDirs attribute to "true". The verbose attribute on delete is set to "true" so that Ant will list each file being deleted.

The completed build.xml can be downloaded here: build.xml.  I also pasted it here:

<?xml version="1.0" ?>

- <project name="UKLights" default="all" basedir=".">

  <property name="src" value="src" />

  <property name="build" value="build" />

  <property name="lib" value="lib" />

- <target name="all" depends="UKLights" description="Builds the whole project">

  <echo>Doing all</echo>

  </target>

- <target name="UKLights" depends="AboutControl,ExitControl" description="Builds the main UKLights project">

  <echo>Doing UKLights</echo>

  <copy file="${src}/UKLights.jpeg" tofile="${build}/UKLights.jpeg" />

  <javac srcdir="${src}" destdir="${build}" includes="UKLights.java" />

  </target>

- <target name="AboutControl" depends="AboutPopup" description="Builds AboutControl">

  <echo>Doing AboutControl</echo>

  <javac srcdir="${src}" destdir="${build}" includes="AboutControl.java" />

  </target>

- <target name="AboutPopup" description="Builds AboutPopup">

  <echo>Doing AboutPopup</echo>

  <javac srcdir="${src}" destdir="${build}" includes="AboutPopup.java" />

  </target>

- <target name="ExitControl" description="Builds ExitControl">

  <echo>Doing ExitControl</echo>

  <javac srcdir="${src}" destdir="${build}" includes="ExitControl.java" />

  </target>

- <target name="Clean" description="Removes previous build">

- <delete verbose="true">

  <fileset dir="${build}" />

  </delete>

  </target>

  </project>

Note that if you do not download the UKLights jpg you’ll have to substitute your own and replace the name in the java source and in the build files. An Aside.  Naming files to be copied explicitly is probably bad practice.  If we plan to copy all of a certain type of file from one dir to another, we could use fileset with the copy.  Fileset is covered later in other tutorials, but here is a fileset that could replace the script element for copying just one jpg with an element to copy all of a certain filetype (in this case, jpg) from one dir to another:

<copy todir="${build}">

     <fileset dir="${src}">

            <include name="*.jpg"/>

            </fileset>

       </copy>

The completed UKLights.java can be downloaded here: UKLights.java.

The project is complete; testing can commence. Execute the "Clean" target to remove the old build:

ant Clean

This produces output similar to:

Buildfile: build.xml

 

Clean:

   [delete] Deleting 2 files from \blah\blah\build

   [delete] Deleting \blah\blah\blah\build\UKLights.class

   [delete] Deleting \blah\blah\blah\build\uklights.jpeg

 

BUILD SUCCESSFUL

Total time: 1 second

   

Run Ant with no arguments so it executes the default target, "all", by typing ant at the command line in the base directory, the output produced is:

Buildfile: build.xml

 

AboutPopup:

     [echo] Doing AboutPopup

    [javac] Compiling 1 source file to \blah\blah\blah\build

 

AboutControl:

     [echo] Doing AboutControl

    [javac] Compiling 1 source file to \blah\blah\blah\build

 

ExitControl:

     [echo] Doing ExitControl

    [javac] Compiling 1 source file to \blah\blah\blah\build

 

UKLights:

     [echo] Doing UKLights

     [copy] Copying 1 file to  \blah\blah\blah\build

    [javac] Compiling 1 source file to \blah\blah\blah\build

 

all:

     [echo] Doing all

 

BUILD SUCCESSFUL

Total time: 4 seconds

   

Notice the order that the targets are executed, first "AboutPopup", then "AboutControl", then "ExitControl" then "UKLights", then finally, "all". This is because the dependencies of a target are exectuted before the target itself. The build was successful as indicated by "BUILD SUCCESSFUL", UKLights.class was created, execute UKLights.class and enjoy the image. The reader should now be able to use Ant in a simple project.

5.A Bit About FileSets

A FileSet is a filter which uses one or more patterns to specify which files are desired. A FileList is a list of desired files. FileSets use PatternSets and Patterns to define their actions.

  • ? is used to match any character.
  • * is used to match zero or more characters.
  • ** is used to match zero or more directories.

A FileSet must specify a base directory from which all other path calculations are made, this is supplied via the dir attribute. A FileSet has the basic form:

<fileset dir="BASEDIR"/>

Or:

<fileset dir="BASEDIR">

</fileset>

Since both of these FileSets contain no patterns, they match the default; every file in the base directory and all its subdirectories, recursively, apart from the files which match the following patterns:

**/*~

**/#*#

**/.#*

**/%*%

**/._*

**/CVS

**/CVS/**

**/.cvsignore

**/SCCS

**/SCCS/**

**/vssver.scc

**/.svn

**/.svn/**

Notice that the sequence "**" is used above to denote zero or more directories, for example, the first pattern matches any file in the base directory or any of it's directories that end with the '~' character, which some common tools use to denote scratch or backup files. The other patterns are excluded for similar reasons.

[Note]

Note

If one desires to delete any of these defaultly excluded files, for example, to delete all scratch files that vim (a text editor) made, recursively, one has to set defaultexcludes="no" so that the defaults are not excluded and then one could use something like:

      <?xml version="1.0"?>

      <project name="Scratch Cleaner" default="clean" basedir=".">

        <target name="clean">

          <echo>Removing temporary files...</echo>

          <delete verbose="true"> <!-- Remove all *~ files -->

            <fileset dir="${basedir}" defaultexcludes="no">

              <include name="**/*~"/>

            </fileset>

          </delete>

        </target>

      </project>

     

<fileset dir="." includes="**/*.blah **/*.bleh"

 

Includes all files ending in the extensions "blah" and "bleh" in the base directory and all subdirectories, the pattern is applied recursively in the subdirectories.

<fileset dir=".">

  <include name="**/*bl*"/>

  <exclude name="**/blah/*"/>

</fileset>

Includes all files that contain the string "bl" in the base directory and all sub directories, recursively. Excludes any files in any directory called "blah", whether it occurs in the current directory or any of the sub directories, recursively. Notice that the syntax is slightly different, in that, include and name are used instead of includes and exclude and name are used instead of excludes.

[Note]

Note

In the context of the sentences above, the word "recursively" means that the pattern is applied to each of the sub-directories as well as the base directory hence it is then applied to the sub-directories of the sub-directories and so on. The pattern is applied to all directories under the base directory.

Patterns can be 'saved' for future use by encapsulating them within a patternset element:

<fileset dir=".">

  <patternset id="blah">

    <include name="**/*bl*"/>

    <exclude name="**/blah/*"/>

  </patternset>

</fileset>

This pattern could be referenced by any other element that supports this kind of referencing:

<fileset dir=">

  <patterset refid="blah"/>

</fileset>

One can also use the if and unless attributes with include and exclude to provide conditional inclusions or exclusions:

<fileset dir=".">

  <include name="**/extensions/*.java" if="version.professional"/>

</fileset>

Which includes all the java files within any sub-directories called "extensions", from the base directory, only if some property called "version.professional" is set.

<fileset dir=".">

  <exclude name="chinese.lang" unless="language.chinese"/>

</fileset>

Which excludes the chinese language module unless the property "language.chinese" is set. If one finds that a lot of include or exclude elements are being used, it can be useful to define the include and exclude elements in an external file. The external file can then be referenced from within a build file with includesfile or excludesfile respectively. The referenced file is treated as having one include or exclude element per line:

<fileset dir=".">

  <includesfile name="some.file"/>

</fileset>

some.file would look like:

bl?h.bl?h

*.java

Notice, that each line contains the value that would be assigned to each of the include statements' name attribute. Similarly, an exludesfile could be specified:

<fileset dir=".">

  <excludesfile name="some.file"/>

</fileset>

some.file would look like:

Test.java

**/extensions/*

build.xml

cool.file

if and unless can be used with includesfile and excludesfile. FileLists specify a list of files and do not support wildcards. The dir attribute specifies the base directory. The files attribute specifies a comma or space separated list of files and the id attribute is optional:

<filelist id="blah" dir="."

files="blah.blah bleh.bleh"/>

ids may be referenced from another filelists:

<filelist refid="blah"/>

I know of no way arbitrarily exclude or include a filelist, for this behaviour use a fileset, patternset or dirset.

6.Advanced Topics

6.1.Flow Of Control

Since Ant does not contain any real control structures like if..then..else, one has to manipulate Ant's ability to call internal targets that support conditional execution to emulate the desired control structures. Consider the control sequence:

if( condition ) {

   if( inner-condition ) {

      A

   } else {

      B

   }

} else {

   C

}

There are three possible routes that the program could take, designated by the actions A, B and C. This can be expressed in Ant as:

<?xml version="1.0"?>

<project name="Flow.Of.Control" default="nested-if" basedir=".">

 

  <target name="nested-if">

    <condition property="condition">

      <available file="fileone"/>

    </condition>

    <antcall target="then"/>

    <antcall target="else"/>

  </target>

 

  <target name="then" if="condition">

    <echo>THEN BODY EXECUTED</echo>

    <condition property="inner-condition">

      <available file="filetwo"/>

    </condition>

    <antcall target="inner.then"/>

    <antcall target="inner.else"/>

  </target>

 

     <target name="inner.then" if="inner-condition">

       <echo>INNER THEN BODY EXECUTED</echo>

     </target>

 

     <target name="inner.else" unless="inner-condition">

       <echo>INNER ELSE BODY EXECUTED</echo>

     </target>

 

  <target name="else" unless="condition">

    <echo>ELSE BODY EXECUTED</echo>

  </target>

</project>

It can be downloaded here: build.xml. A diagram which attempts to clarify the location of the various components of the control structure is shown below:

Figure1.Nested If..Then..Else In Ant

Nested If..Then..Else In Ant

Assuming the case where the first file, fileone, and the second file, filetwo are not available. The initial condition checks if the file fileone available, if it is, the property condition is set. Calls to the targets then and else follow. The execution of then is conditional, dictated by (if="condition"). Since the assumption is fileone is not available, condition will not be set and the body of then will not be executed. The next target, else, will be called. The execution of else is conditional, dictated by (unless="condition") which means that the body will be executed unlesscondition is set. Since condition has not been set, the body of else will be executed. The output from simulating this by running ant on the build file with the files fileone and filetwo not available is shown below:

Figure2.Output produced when ant is ran when fileone and filetwo are not available

Output produced when ant is ran when fileone and filetwo are not available

Assuming the case where the first file, fileone, is present, and the second file, filetwo is not. The initial condition will be set because fileone is available so the call to then will be successful. The body of then contains another condition which checks for the existence of the file filetwo, if it is available, the property, inner-condition is set. Since the assumption is that filetwo is not available, the property inner-condition will not be set. Calls to the targets inner.then and inner.else follow. The execution of inner.then is conditional, dictated by (if="inner-condition") so the body of inner.then will not be executed. The execution of inner.else is conditional, dictated by (unless="inner-condition") so the body of inner.else will be executed since the only thing that would stop the execution of it would be if inner-condition was set. The output from simulating this by running ant on the build file with the file fileone available and the file filetwo not available is shown below:

Figure3.Output produced when ant is run with fileone available and filetwo not available

Output produced when ant is ran with fileone available and filetwo not available

Upon exiting the call to then, the target else will be called but the body will not be executed because the condition (unless="condition"), specifies that if condition is set, the target should not be executed.

Assuming the case where the first file, fileone, and the second file, filetwo are both available. The outer condition will cause the property condition to be set because fileone is available, so when the target then is called, the body will be executed. The condition within then will cause the property inner-condition to be set because filetwo is available. This means that the call to inner.then will be successful. Upon exiting inner.then, inner.else will be called but the body will not be executed because inner-condition is set. Upon exiting then, else will be called but the body will not be executed because condition is set. The output from simulating this by running ant on the build file with the files, fileone and filetwo, available is shown below:

Figure4.Output produced when ant is ran with fileone and filetwo both available

Output produced when ant is ran with fileone and filetwo both available

 

 

And here’s one from Jakarta: http://ant.apache.org/manual/tutorial-HelloWorldWithAnt.html

Tutorial #1: Hello World with Ant

Besides ant build scripts, this includes logging and testing.

This document provides a step by step tutorial for starting java programming with Ant. It does not contain deeper knowledge about Java or Ant. This tutorial has the goal to let you see, how to do the easiest steps in Ant.

Preparing the project

We want to separate the source from the generated files, so our java source files will be in src folder. All generated files should be under build, and there splitted into several subdirectories for the individual steps: classes for our compiled files and jar for our own JAR-file.

We have to create only the src directory. (Because I am working on Windows, here is the win-syntax - translate to your shell):

md src

The following simple Java class just prints a fixed message out to STDOUT, so just write this code into src\oata\HelloWorld.java.

package oata;
 
public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello World");
    }
}

Now just try to compile and run that:

md build\classes
javac -sourcepath src -d build\classes src\oata\HelloWorld.java
java -cp build\classes oata.HelloWorld

which will result in

Hello World

Creating a jar-file is not very difficult. But creating a startable jar-file needs more steps: create a manifest-file containing the start class, creating the target directory and archiving the files.

echo Main-Class: oata.HelloWorld>myManifest
md build\jar
jar cfm build\jar\HelloWorld.jar myManifest -C build\classes .
java -jar build\jar\HelloWorld.jar

Note: Do not have blanks around the >-sign in the echo Main-Class instruction because it would falsify it!

Four steps to a running application

After finishing the java-only step we have to think about our build process. We have to compile our code, otherwise we couldn't start the program. Oh - "start" - yes, we could provide a target for that. We should package our application. Now it's only one class - but if you want to provide a download, no one would download several hundreds files ... (think about a complex Swing GUI - so let us create a jar file. A startable jar file would be nice ... And it's a good practise to have a "clean" target, which deletes all the generated stuff. Many failures could be solved just by a "clean build".

By default Ant uses build.xml as the name for a buildfile, so our .\build.xml would be:

<project>
 
    <target name="clean">
        <delete dir="build"/>
    </target>
 
    <target name="compile">
        <mkdir dir="build/classes"/>
        <javac srcdir="src" destdir="build/classes"/>
    </target>
 
    <target name="jar">
        <mkdir dir="build/jar"/>
        <jar destfile="build/jar/HelloWorld.jar" basedir="build/classes">
            <manifest>
                <attribute name="Main-Class" value="oata.HelloWorld"/>
            </manifest>
        </jar>
    </target>
 
    <target name="run">
        <java jar="build/jar/HelloWorld.jar" fork="true"/>
    </target>
 
</project>

Now you can compile, package and run the application via

ant compile
ant jar
ant run

Or shorter with

ant compile jar run
 
Here’s just the run task:
C:\ant_tutorial2>ant run
Buildfile: build.xml
 
run:
     [java] Hello World
 
BUILD SUCCESSFUL
Total time: 0 seconds
C:\ant_tutorial2>

While having a look at the buildfile, we will see some similar steps between Ant and the java-only commands:

java-only

Ant

md build\classes
javac
    -sourcepath src
    -d build\classes
    src\oata\HelloWorld.java
echo Main-Class: oata.HelloWorld>mf
md build\jar
jar cfm
    build\jar\HelloWorld.jar
    mf
    -C build\classes
    .
 
 
 
java -jar build\jar\HelloWorld.jar
  
<mkdir dir="build/classes"/>
<javac
    srcdir="src"
    destdir="build/classes"/>
<!-- automatically detected -->
<!-- obsolete; done via manifest tag -->
<mkdir dir="build/jar"/>
<jar
    destfile="build/jar/HelloWorld.jar"
 
    basedir="build/classes">
    <manifest>
        <attribute name="Main-Class" value="oata.HelloWorld"/>
    </manifest>
</jar>
<java jar="build/jar/HelloWorld.jar" fork="true"/>
  

Enhance the build file

Now we have a working buildfile we could make some improvements to get rid of repetition and hard-coded values. Additionally, to use this build, we need to remember the order in which to call tasks.  These issues can be resolved with properties, along with defining task dependencies.

<project name="HelloWorld" basedir="." default="main">
 
    <property name="src.dir"     value="src"/>
 
    <property name="build.dir"   value="build"/>
    <property name="classes.dir" value="${build.dir}/classes"/>
    <property name="jar.dir"     value="${build.dir}/jar"/>
 
    <property name="main-class"  value="oata.HelloWorld"/>
 
 
 
    <target name="clean">
        <delete dir="${build.dir}"/>
    </target>
 
    <target name="compile">
        <mkdir dir="${classes.dir}"/>
        <javac srcdir="${src.dir}" destdir="${classes.dir}"/>
    </target>
 
    <target name="jar" depends="compile">
        <mkdir dir="${jar.dir}"/>
        <jar destfile="${jar.dir}/${ant.project.name}.jar" basedir="${classes.dir}">
            <manifest>
                <attribute name="Main-Class" value="${main-class}"/>
            </manifest>
        </jar>
    </target>
 
    <target name="run" depends="jar">
        <java jar="${jar.dir}/${ant.project.name}.jar" fork="true"/>
    </target>
 
    <target name="clean-build" depends="clean,jar"/>
 
    <target name="main" depends="clean,run"/>
 
</project>

Now it's easier, just do a ant and you will get

Buildfile: build.xml
 
clean:
 
compile:
    [mkdir] Created dir: C:\...\build\classes
    [javac] Compiling 1 source file to C:\...\build\classes
 
jar:
    [mkdir] Created dir: C:\...\build\jar
      [jar] Building jar: C:\...\build\jar\HelloWorld.jar
 
run:
     [java] Hello World
 
main:
 
BUILD SUCCESSFUL

Using external libraries

Another aside: You can’t put into a lib folder a jar which is part of java, like j2ee.jar

Avoid System out  for logging (referred to here as SysO).  For log-Statements we should use a Logging-API - customizable on a high degree (including switching off during usual life (= not development) execution). We use Log4J for that, because

  • it is not part of the JDK (1.4+) and we want to show how to use external libs
  • it can run under JDK 1.2 (as Ant)
  • it's highly configurable
  • it's from Apache ;-)

We store our external libraries in a new directory lib. Log4J can be found at  http://www.alliedquotes.com/mirrors/apache/logging/log4j/1.2.15/apache-log4j-1.2.15.zip. Create the lib directory and extract the log4j-1.2.9.jar into that lib-directory. After that we have to modify our java source to use that library and our buildfile so that this library could be accessed during compilation and run.

Working with Log4J is documented inside its manual. Here we use the MyApp-example from the Short Manual [2]. First we have to modify the java source to use the logging framework:

package oata;
 
import org.apache.log4j.Logger;
import org.apache.log4j.BasicConfigurator;
 
public class HelloWorld {
    static Logger logger = Logger.getLogger(HelloWorld.class);
 
    public static void main(String[] args) {
        BasicConfigurator.configure();
        logger.info("Hello World");          // the old SysO-statement
    }
}

Most of the modifications are "framework overhead" which has to be done once. The blue line is our "old System-out" statement.

Don't try to run ant - you will only get lot of compiler errors. Log4J is not inside the classpath so we have to do a little work here. But do not change the CLASSPATH environment variable! This is only for this project and maybe you would break other environments (this is one of the most famous mistakes when working with Ant). We introduce Log4J (or to be more precise: all libraries (jar-files) which are somewhere under .\lib) into our buildfile:

<project name="HelloWorld" basedir="." default="main">
    ...
    <property name="lib.dir"     value="lib"/>
 
    <path id="classpath">
        <fileset dir="${lib.dir}" includes="**/*.jar"/>
    </path>
 
    ...
 
    <target name="compile">
        <mkdir dir="${classes.dir}"/>
        <javac srcdir="${src.dir}" destdir="${classes.dir}" classpathref="classpath"/>
    </target>
 
    <target name="run" depends="jar">
        <java fork="true" classname="${main-class}">
            <classpath>
                <path refid="classpath"/>
                <path location="${jar.dir}/${ant.project.name}.jar"/>
            </classpath>
        </java>
    </target>
 
    ...
 
</project>

In this example we start our application not via its Main-Class manifest-attribute, because we could not provide a jarname and a classpath. So add our class in the red line to the already defined path and start as usual. Running ant would give (after the usual compile stuff):

[java] 0 [main] INFO oata.HelloWorld  - Hello World

What's that?

  • [java] Ant task running at the moment
  • 0 sorry don't know - some Log4J stuff
  • [main] the running thread from our application
  • INFO log level of that statement
  • oata.HelloWorld source of that statement
  • - separator
  • Hello World the message

For another layout ... have a look inside Log4J's documentation about using other PatternLayout's.

Configuration files

Why we have used Log4J? "It's highly configurable"? No - all is hard coded! But that is not the debt of Log4J - it's ours. We had coded BasicConfigurator.configure(); which implies a simple, but hard coded configuration. Better to use a property file. In the java source delete the BasicConfiguration-line from the main() method (and the related import-statement). Log4J will search then for a configuration as described in it's manual. Then create a new file src/log4j.properties. That's the default name for Log4J's configuration and using that name would make life easier - not only the framework knows what is inside, you too!

log4j.rootLogger=DEBUG, stdout
 
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
 
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%m%n

This configuration creates an output channel ("Appender") to console named as stdout which prints the message (%m) followed by a line feed (%n) - same as the earlier System.out.println() :-) Oooh kay - but we haven't finished yet. We should deliver the configuration file, too. So we change the buildfile:

    ...
    <target name="compile">
        <mkdir dir="${classes.dir}"/>
        <javac srcdir="${src.dir}" destdir="${classes.dir}" classpathref="classpath"/>
        <copy todir="${classes.dir}">
            <fileset dir="${src.dir}" excludes="**/*.java"/>
        </copy>
    </target>
    ...

This copies all resources (as long as they haven't the suffix ".java") to the build directory, so we could start the application from that directory and these files will included into the jar.

It still works: here’s blackscreen output:

C:\ant_tutorial2>ant

Buildfile: build.xml

clean:

   [delete] Deleting directory C:\ant_tutorial2\build

compile:

    [mkdir] Created dir: C:\ant_tutorial2\build\classes

    [javac] Compiling 1 source file to C:\ant_tutorial2\build\classes

     [copy] Copying 1 file to C:\ant_tutorial2\build\classes

jar:

    [mkdir] Created dir: C:\ant_tutorial2\build\jar

      [jar] Building jar: C:\ant_tutorial2\build\jar\HelloWorld.jar

run:

     [java] Hello World

main:

BUILD SUCCESSFUL

Total time: 5 seconds

Testing the class

In this step we will introduce the usage of the JUnit [3] testframework in combination with Ant. Because Ant has a built-in JUnit 3.8.2 you could start directly using it. Write a test class in src\HelloWorldTest.java:

public class HelloWorldTest extends junit.framework.TestCase {
 
    public void testNothing() {
    }
    
    public void testWillAlwaysFail() {
        fail("An error message");
    }
    
}

Because we dont have real business logic to test, this test class is very small: it merely shows how to set up a test. For further information see the JUnit documentation [3] and the manual of junit task. Now we add a junit instruction to our buildfile:

    ...
 
    <target name="run" depends="jar">
        <java fork="true" classname="${main-class}">
            <classpath>
                <path refid="classpath"/>
                <path id="application" location="${jar.dir}/${ant.project.name}.jar"/>
            </classpath>
        </java>
    </target>
    
    <target name="junit" depends="jar">
        <junit printsummary="yes">
            <classpath>
                <path refid="classpath"/>
                <path refid="application"/>
            </classpath>
            
            <batchtest fork="yes">
                <fileset dir="${src.dir}" includes="*Test.java"/>
            </batchtest>
        </junit>
    </target>
 
    ...
 

We reuse the path to our own jar file as defined in run-target by giving it an ID. The printsummary=yes lets us see more detailed information than just a "FAILED" or "PASSED" message. How much tests failed? Some errors? Printsummary lets us know. The classpath is set up to find our classes. To run tests the batchtest here is used, so you could easily add more test classes in the future just by naming them *Test.java. This is a common naming scheme.

I had to download junit.jar and stick it into ant\lib directory to get this part to compile and run and even then this “test fail” output is not happening for me.

After ant junit you'll get:

...
junit:
    [junit] Running HelloWorldTest
    [junit] Tests run: 2, Failures: 1, Errors: 0, Time elapsed: 0,01 sec
    [junit] Test HelloWorldTest FAILED
 
BUILD SUCCESSFUL
...

We can also produce a report. Something that you (and other) could read after closing the shell .... There are two steps: 1. let <junit> log the information and 2. convert these to something readable (browsable).

    ...
    <property name="report.dir"  value="${build.dir}/junitreport"/>
    ...
    <target name="junit" depends="jar">
        <mkdir dir="${report.dir}"/>
        <junit printsummary="yes">
            <classpath>
                <path refid="classpath"/>
                <path refid="application"/>
            </classpath>
            
            <formatter type="xml"/>
            
            <batchtest fork="yes" todir="${report.dir}">
                <fileset dir="${src.dir}" includes="*Test.java"/>
            </batchtest>
        </junit>
    </target>
    
    <target name="junitreport">
        <junitreport todir="${report.dir}">
            <fileset dir="${report.dir}" includes="TEST-*.xml"/>
            <report todir="${report.dir}"/>
        </junitreport>
    </target>

Because we would produce a lot of files and these files would be written to the current directory by default, we define a report directory, create it before running the junit and redirect the logging to it. The log format is XML so junitreport could parse it. In a second target junitreport should create a browsable HTML-report for all generated xml-log files in the report directory. Now you can open the ${report.dir}\index.html and see the result (looks something like JavaDoc).
Personally I use two different targets for junit and junitreport. Generating the HTML report needs some time and you dont need the HTML report just for testing, e.g. if you are fixing an error or a integration server is doing a job.

Ant tutorial #2

Here’s another with some duplication, but it covers javadoc generation and has as an example a webapp project.

 

This from site:

http://www.javaworld.com/javaworld/jw-10-2000/jw-1020-ant.html

 

A defined process is one of the most necessary but often least-used tools in software development. It is by nature an overhead task that accompanies a development effort. A defined build process ensures that the software in your development project is built in the exact same manner each time a build is executed. As the build process becomes more complex -- for example, with EJB builds or additional tasks -- it becomes more necessary to achieve such standardization. You should establish, document, and automate the exact series of steps as much as possible.

Why do I need a defined build process?

A defined build process is an essential part of any development cycle because it helps close the gap between the development, integration, test, and production environments. A build process alone will speed the migration of software from one environment to another. It also removes many issues related to compilation, classpath, or properties that cost many projects time and money.

What is Ant?

Ant is a platform-independent scripting tool that lets you construct your build scripts in much the same fashion as the "make" tool in C or C++. You can use a large number of built-in tasks in Ant without any customization. Some of the most important tasks are shown in the following table but explained in more detail in the example that follows.

 

Command

Description

Ant

Used to execute another ant process from within the current one.

Copydir

Used to copy an entire directory.

Copyfile

Used to copy a single file.

Cvs

Handles packages/modules retrieved from a CVS repository.

Delete

Deletes either a single file or all files in a specified directory and its sub-directories.

Deltree

Deletes a directory with all its files and subdirectories.

Exec

Executes a system command. When the os attribute is specified, then the command is only executed when Ant is run on one of the specified operating systems.

Get

Gets a file from an URL.

Jar

Jars a set of files.

Java

Executes a Java class within the running (Ant) VM or forks another VM if specified.

Javac

Compiles a source tree within the running (Ant) VM.

Javadoc/Javadoc2

Generates code documentation using the javadoc tool.

Mkdir

Makes a directory.

Property

Sets a property (by name and value), or set of properties (from file or resource) in the project.

Rmic

Runs the rmic compiler for a certain class.

Tstamp

Sets the DSTAMP, TSTAMP, and TODAY properties in the current project.

Style

Processes a set of documents via XSLT.

 

While other tools are available for doing software builds, Ant is easy to use and can be mastered within minutes. In addition, Ant lets you create expanded functionality by extending some of its classes. I will show this expansion in a following example.

What do I need to use Ant?

You must install three components on your machine to run Ant: JDK, XML parser, and Ant (see Resources for links).

In many cases, the XML parser is part of the lib files distributed with the Servlet runner or the Web Server. If not, the free XML parser from java.sun.com is sufficient.

Ant installation consists of downloading the files, adding the class libraries to the classpath, and adding the Ant binaries to the path.

Example scenario

This example scenario should help show you the value of Ant and provide insight into its benefits and how you can use it.

Because a large amount of the current Java development is focused on server-side Java, I have chosen a server-side application for the example. Developers working on server-side Java applications are typically interested in the compilation of servlets, deployment of JSP files, and deployment of HTML files, configuration files, or images.

A common scheme for doing this build would involve the development of small scripts in platform-specific languages based on the server's operating system. For example, a developer working on an NT machine could create a batch file that performs the compilation tasks and then runs the deployment. However, if the production environment had Unix or Linux, the developer would have to rewrite the script, ensuring that the scripts were in sync.

OK, show me how this works

So, I've hopefully convinced you of the need to use Ant and shown how simple it is to install. Now I'll show you how simple Ant is to use by stepping through an example that performs simple compilation and deployment.

Simple build process with Ant (simple.xml)

<project name="simpleCompile" default="deploy" basedir=".">
   <target name="init">
      <property name="sourceDir" value="src"/ >
      <property name="outputDir" value="classes" />
      <property name="deployJSP" value="/web/deploy/jsp" />
      <property name="deployProperties" value="/web/deploy/conf" />
   </target>
   <target name="clean" depends="init">
      <deltree dir="${outputDir}" />
   </target>
   <target name="prepare" depends="clean">
      <mkdir dir="${outputDir}" />
   </target>
   <target name="compile" depends="prepare">
     <javac srcdir="${sourceDir}" destdir="${outputDir}" />
   </target>
   <target name="deploy" depends="compile,init">
     <copydir src="${jsp}" dest="${deployJSP}"/>
     <copyfile src="server.properties" dest="${deployProperties}"/>
   </target>
</project>

 

There's a lot to explain in the above example. First, you should understand the structure of the simple.xml file. It is a well-formatted XML file containing a project entity that is comprised of several target entities.

The first line contains information about the overall project that is to be built.

<project name="simpleCompile" default="deploy" basedir=".">

 

The most important elements of the project line are the default and the basedir.

The default attribute references the default target that is to be executed. Because Ant is a command-line build tool, it is possible to execute only a subset of the target steps in the Ant file. For example, I could perform the following command:

% ant -buildfile simple.xml init

 

That will execute the ant command and run through the simple.xml file until the init target is reached. So, in this example, the default is deploy. The Ant process invoked in the following line will run through the simple.xml file until the deploy command is reached:

% ant -buildfile simple.xml

 

The basedir attribute is fairly self-explanatory as it is the base directory from which the relative references contained in the build file are retrieved. Each project can have only one basedir attribute so you can choose to either include the fully qualified directory location or break the large project file into smaller project files with different basedir attributes.

The next line of interest is the target line. Two different versions are shown here:

   <target name="init">
   <target name="clean" depends="init">

 

The target element contains four attributes: name, if, unless, and depends. Ant requires the name attribute, but the other three attributes are optional.

Using depends, you can stack the Ant tasks so that a dependent task is not initiated until the task that it depends on is completed. In the above example, the clean task will not start until the init task has completed. The depends attribute may also contain a list of comma-separated values indicating several tasks that the task in discussion depends on.

The if and unless commands let you specify commands that are to be performed either if a certain property is set or unless that property is set. The if will execute when the property value is set, and the unless will execute if the value is not set. You can use the available command to set those properties as shown in a following example, or you can set them via the command line.

The init target from the simple example contains four lines of property commands as shown here:

      <property name="sourceDir" value="src" />

 

These property lines let you specify commonly used directories or files. A property is a simple name value pair that allows you to refer to the directory or file as a logical entity rather than a physical one.

If you wanted to reference the sourceDir variable later in the Ant file, you could simply use the following syntax to alert Ant to obtain the value for this tag: ${sourceDir}.

Two other commands present in the above buildfile are:

      <deltree dir="${ outputDir }" />
      <mkdir dir="${ outputDir }" />

 

These commands are used to ensure that there are no extraneous files in the outputDir (or classes directory when dereferenced as mentioned above). The first command removes the entire tree contained under the outputDir. The second command creates the directory again.

The last line of major interest to the developer is the following compilation line:

     <javac srcdir="${sourceDir}" destdir="${outputDir}" />

 

The javac command requires a source directory (the input location of the .java files) and a destination directory (the output location of the .classes file). It is important to note that all directories must either exist prior to the running of the ant command or be created using the mkdir command. Ant does not create directories based upon intuition, so you must create the outputDir, using the mkdir command prior to the compilation step above.

After the compile task has completed, the deploy task will perform the copy operation to move all JSP files from the source directory to a deployment directory. By using the copydir command, you copy the entire JSP directory from one location to another. I used the copyfile command to copy a single properties file as part of the build.

While it took several lines to explain the example, it should be evident that Ant is an easy-to-use tool. Using this buildfile as a starting point, you should be able to incorporate Ant into your development effort. The ant commands shown in the above example have further functionality, some of which will be discussed in this article, the remainder is left to you along with references to the documentation.

Important tasks

It is left to you to read through the built-in tasks included in the Ant distribution. See the user guide in Resources for information about each command. I have chosen two commonly used commands as examples of additional options available to the build manager without any customization.

Compiling code (including EJBs)

In the simple example discussed earlier, you saw a simple form of the javac command. Now, if you examine it in more detail, you see that you can specify the compilation flags such as deprecation, debug, or optimize as well as the files that will or will not be included in the compilation.

    <javac srcdir="${src.dir}"
           destdir="${build.classes}"
           classpath="${classpath}"
           debug="on"
           deprecation="off"
           optimize="on" >
      <include name="**/*.java"/>
      <exclude name="**/Script.java" unless="bsf.present" />
      <exclude name="**/version.txt" />
    </javac>

 

You can use the include/exclude entities inside the javac task to include/exclude files matching the pattern in the name attribute from the compilation. From the above example, you want to include files contained in any directory ending in .java but, at the same time, you want to exclude files named Script.java unless a property bsf.present is set to true.

You set the bsf.present property using the following task that searches the classpath for the classname specified and sets bsf.present according to the search results:

    <available property="bsf.present" classname="com.ibm.bsf.BSFManager" />

 

The javac command will not include files called version.txt from the compilation based upon the exclude command above.

Generating javadoc

Another task that Ant can help automate is the generation of javadoc. You can use the following command to generate the javadoc:

    <javadoc packagenames="${packages}"
             sourcepath="${basedir}/${src.dir}"
             destdir="${build.javadocs}"
             author="true"
             version="true"
             windowtitle="${Name} API"
             doctitle="${Name}"
             bottom="Copyright © 2000 GroupServe. All Rights Reserved."
    />

 

The packages specify the overall packages that the javadoc will include. The sourcepath attribute points towards the location of the source files. The javadoc command also provides attributes allowing you to specify the title of the window and the document. You can also include a copyright notice at the bottom of each javadoc page, using the bottom attribute.

 

There are many other ant tutorials on the web.

 

Further examples

 

 

Requirements: download apache ant.  Configure path settings (in control panel env variables). You may wish to work through a simple ant tutorial.

 

 

About ant build file.   This explanation from apache http://tomcat.apache.org/tomcat-4.1-doc/appdev/build.xml.txt

 

<!—

     General purpose build script for web applications and web services,
     including enhanced support for deploying directly to a Tomcat 4
     based server.
 
     This build script assumes that the source code of your web application
     is organized into the following subdirectories underneath the source
     code directory from which you execute the build script:
 
        docs                 Static documentation files to be copied to
                             the "docs" subdirectory of your distribution.
 
        src                  Java source code (and associated resource files)
                             to be compiled to the "WEB-INF/classes"
                             subdirectory of your web applicaiton.
 
        web                  Static HTML, JSP, and other content (such as
                             image files), including the WEB-INF subdirectory
                             and its configuration file contents.
 
     $Id: build.xml.txt 288993 2004-05-23 19:47:19Z markt $
-->
 
 
<!-- A "project" describes a set of targets that may be requested
     when Ant is executed.  The "default" attribute defines the
     target which is executed if no specific target is requested,
     and the "basedir" attribute defines the current working directory
     from which Ant executes the requested task.  This is normally
     set to the current working directory.
-->
 
<project name="My Project" default="compile" basedir=".">
 
 
 
<!-- ===================== Property Definitions =========================== -->
 
 
<!--
 
  Each of the following properties are used in the build script.
  Values for these properties are set by the first place they are
  defined, from the following list:
 
  * Definitions on the "ant" command line (ant -Dfoo=bar compile).
 
  * Definitions from a "build.properties" file in the top level
    source directory of this application.
 
  * Definitions from a "build.properties" file in the developer's
    home directory.
 
  * Default definitions in this build.xml file.
 
  You will note below that property values can be composed based on the
  contents of previously defined properties.  This is a powerful technique
  that helps you minimize the number of changes required when your development
  environment is modified.  Note that property composition is allowed within
  "build.properties" files as well as in the "build.xml" script.
 
-->
 
  <property file="build.properties"/>
  <property file="${user.home}/build.properties"/>
 
 
<!-- ==================== File and Directory Names ======================== -->
 
 
<!--
 
  These properties generally define file and directory names (or paths) that
  affect where the build process stores its outputs.
 
  app.name             Base name of this application, used to
                       construct filenames and directories.
                       Defaults to "myapp".
 
  app.path             Context path to which this application should be
                       deployed (defaults to "/" plus the value of the
                       "app.name" property).
 
  app.version          Version number of this iteration of the application.
 
  build.home           The directory into which the "prepare" and
                       "compile" targets will generate their output.
                       Defaults to "build".
 
  catalina.home        The directory in which you have installed
                       a binary distribution of Tomcat 4.  This will
                       be used by the "deploy" target.
 
  dist.home            The name of the base directory in which
                       distribution files are created.
                       Defaults to "dist".
 
  manager.password     The login password of a user that is assigned the
                       "manager" role (so that he or she can execute
                       commands via the "/manager" web application)
 
  manager.url          The URL of the "/manager" web application on the
                       Tomcat installation to which we will deploy web
                       applications and web services.
 
  manager.username     The login username of a user that is assigned the
                       "manager" role (so that he or she can execute
                       commands via the "/manager" web application)
 
-->
 
  <property name="app.name"      value="myapp"/>
  <property name="app.path"      value="/${app.name}"/>
  <property name="app.version"   value="0.1-dev"/>
  <property name="build.home"    value="${basedir}/build"/>
  <property name="catalina.home" value="../../../.."/> <!-- UPDATE THIS! -->
  <property name="dist.home"     value="${basedir}/dist"/>
  <property name="docs.home"     value="${basedir}/docs"/>
  <property name="manager.url"   value="http://localhost:8080/manager"/>
  <property name="src.home"      value="${basedir}/src"/>
  <property name="web.home"      value="${basedir}/web"/>
 
 
<!-- ================== Custom Ant Task Definitions ======================= -->
 
 
<!--
 
  These properties define custom tasks for the Ant build tool that interact
  with the "/manager" web application installed with Tomcat 4.  Before they
  can be successfully utilized, you must perform the following steps:
 
  - Copy the file "server/lib/catalina-ant.jar" from your Tomcat 4
    installation into the "lib" directory of your Ant installation.
 
  - Create a "build.properties" file in your application's top-level
    source directory (or your user login home directory) that defines
    appropriate values for the "manager.password", "manager.url", and
    "manager.username" properties described above.
 
  For more information about the Manager web application, and the functionality
  of these tasks, see <http://localhost:8080/tomcat-docs/manager-howto.html>.
 
-->
 
  <taskdef name="install" classname="org.apache.catalina.ant.InstallTask"/>
  <taskdef name="list"    classname="org.apache.catalina.ant.ListTask"/>
  <taskdef name="reload"  classname="org.apache.catalina.ant.ReloadTask"/>
  <taskdef name="remove"  classname="org.apache.catalina.ant.RemoveTask"/>
 
 
<!--  ==================== Compilation Control Options ==================== -->
 
<!--
 
  These properties control option settings on the Javac compiler when it
  is invoked using the <javac> task.
 
  compile.debug        Should compilation include the debug option?
 
  compile.deprecation  Should compilation include the deprecation option?
 
  compile.optimize     Should compilation include the optimize option?
 
-->
 
  <property name="compile.debug"       value="true"/>
  <property name="compile.deprecation" value="false"/>
  <property name="compile.optimize"    value="true"/>
 
 
 
<!-- ==================== External Dependencies =========================== -->
 
 
<!--
 
  Use property values to define the locations of external JAR files on which
  your application will depend.  In general, these values will be used for
  two purposes:
  * Inclusion on the classpath that is passed to the Javac compiler
  * Being copied into the "/WEB-INF/lib" directory during execution
    of the "deploy" target.
 
  Because we will automatically include all of the Java classes that Tomcat 4
  exposes to web applications, we will not need to explicitly list any of those
  dependencies.  You only need to worry about external dependencies for JAR
  files that you are going to include inside your "/WEB-INF/lib" directory.
 
-->
 
<!-- Dummy external dependency -->
<!--
  <property name="foo.jar"
           value="/path/to/foo.jar"/>
-->
 
 
<!-- ==================== Compilation Classpath =========================== -->
 
<!--
 
  Rather than relying on the CLASSPATH environment variable, Ant includes
  features that makes it easy to dynamically construct the classpath you
  need for each compilation.  The example below constructs the compile
  classpath to include the servlet.jar file, as well as the other components
  that Tomcat makes available to web applications automatically, plus anything
  that you explicitly added.
 
-->
 
  <path id="compile.classpath">
 
    <!-- Include all JAR files that will be included in /WEB-INF/lib -->
    <!-- *** CUSTOMIZE HERE AS REQUIRED BY YOUR APPLICATION *** -->
<!--
    <pathelement location="${foo.jar}"/>
-->
 
    <!-- Include all elements that Tomcat exposes to applications -->
    <pathelement location="${catalina.home}/common/classes"/>
    <fileset dir="${catalina.home}/common/endorsed">
      <include name="*.jar"/>
    </fileset>
    <fileset dir="${catalina.home}/common/lib">
      <include name="*.jar"/>
    </fileset>
    <pathelement location="${catalina.home}/shared/classes"/>
    <fileset dir="${catalina.home}/shared/lib">
      <include name="*.jar"/>
    </fileset>
 
  </path>
 
 
 
<!-- ==================== All Target ====================================== -->
 
<!--
 
  The "all" target is a shortcut for running the "clean" target followed
  by the "compile" target, to force a complete recompile.
 
-->
 
  <target name="all" depends="clean,compile"
   description="Clean build and dist directories, then compile"/>
 
 
 
<!-- ==================== Clean Target ==================================== -->
 
<!--
 
  The "clean" target deletes any previous "build" and "dist" directory,
  so that you can be ensured the application can be built from scratch.
 
-->
 
  <target name="clean"
   description="Delete old build and dist directories">
    <delete dir="${build.home}"/>
    <delete dir="${dist.home}"/>
  </target>
 
 
 
<!-- ==================== Compile Target ================================== -->
 
<!--
 
  The "compile" target transforms source files (from your "src" directory)
  into object files in the appropriate location in the build directory.
  This example assumes that you will be including your classes in an
  unpacked directory hierarchy under "/WEB-INF/classes".
 
-->
 
  <target name="compile" depends="prepare"
   description="Compile Java sources">
 
    <!-- Compile Java classes as necessary -->
    <mkdir    dir="${build.home}/WEB-INF/classes"/>
    <javac srcdir="${src.home}"
          destdir="${build.home}/WEB-INF/classes"
            debug="${compile.debug}"
      deprecation="${compile.deprecation}"
         optimize="${compile.optimize}">
        <classpath refid="compile.classpath"/>
    </javac>
 
    <!-- Copy application resources -->
    <copy  todir="${build.home}/WEB-INF/classes">
      <fileset dir="${src.home}" excludes="**/*.java"/>
    </copy>
 
  </target>
 
 
 
<!-- ==================== Dist Target ===================================== -->
 
 
<!--
 
  The "dist" target creates a binary distribution of your application
  in a directory structure ready to be archived in a tar.gz or zip file.
  Note that this target depends on two others:
 
  * "compile" so that the entire web application (including external
    dependencies) will have been assembled
 
  * "javadoc" so that the application Javadocs will have been created
 
-->
 
  <target name="dist" depends="compile,javadoc"
   description="Create binary distribution">
 
    <!-- Copy documentation subdirectories -->
    <mkdir   dir="${dist.home}/docs"/>
    <copy    todir="${dist.home}/docs">
      <fileset dir="${docs.home}"/>
    </copy>
 
    <!-- Create application JAR file -->
    <jar jarfile="${dist.home}/${app.name}-${app.version}.war"
         basedir="${build.home}"/>
 
    <!-- Copy additional files to ${dist.home} as necessary -->
 
  </target>
 
 
 
<!-- ==================== Install Target ================================== -->
 
<!--
 
  The "install" target tells the specified Tomcat 4 installation to dynamically
  install this web application and make it available for execution.  It does
  *not* cause the existence of this web application to be remembered across
  Tomcat restarts; if you restart the server, you will need to re-install all
  this web application.
 
  If you have already installed this application, and simply want Tomcat to
  recognize that you have updated Java classes (or the web.xml file), use the
  "reload" target instead.
 
  NOTE:  This target will only succeed if it is run from the same server that
  Tomcat is running on.
 
  NOTE:  This is the logical opposite of the "remove" target.
 
-->
 
  <target name="install" depends="compile"
   description="Install application to servlet container">
 
    <install url="${manager.url}"
        username="${manager.username}"
        password="${manager.password}"
            path="${app.path}"
             war="file://${build.home}"/>
 
  </target>
 
 
<!-- ==================== Javadoc Target ================================== -->
 
<!--
 
  The "javadoc" target creates Javadoc API documentation for the Java
  classes included in your application.  Normally, this is only required
  when preparing a distribution release, but is available as a separate
  target in case the developer wants to create Javadocs independently.
 
-->
 
  <target name="javadoc" depends="compile"
   description="Create Javadoc API documentation">
 
    <mkdir          dir="${dist.home}/docs/api"/>
    <javadoc sourcepath="${src.home}"
                destdir="${dist.home}/docs/api"
           packagenames="*">
      <classpath refid="compile.classpath"/>
    </javadoc>
 
  </target>
 
 
 
<!-- ====================== List Target =================================== -->
 
<!--
 
  The "list" target asks the specified Tomcat 4 installation to list the
  currently running web applications, either loaded at startup time or
  installed dynamically.  It is useful to determine whether or not the
  application you are currently developing has been installed.
 
-->
 
  <target name="list"
   description="List installed applications on servlet container">
 
    <list    url="${manager.url}"
        username="${manager.username}"
        password="${manager.password}"/>
 
  </target>
 
 
<!-- ==================== Prepare Target ================================== -->
 
<!--
 
  The "prepare" target is used to create the "build" destination directory,
  and copy the static contents of your web application to it.  If you need
  to copy static files from external dependencies, you can customize the
  contents of this task.
 
  Normally, this task is executed indirectly when needed.
 
-->
 
  <target name="prepare">
 
    <!-- Create build directories as needed -->
    <mkdir  dir="${build.home}"/>
    <mkdir  dir="${build.home}/WEB-INF"/>
    <mkdir  dir="${build.home}/WEB-INF/classes"/>
 
 
    <!-- Copy static content of this web application -->
    <copy todir="${build.home}">
      <fileset dir="${web.home}"/>
    </copy>
 
    <!-- Copy external dependencies as required -->
    <!-- *** CUSTOMIZE HERE AS REQUIRED BY YOUR APPLICATION *** -->
    <mkdir  dir="${build.home}/WEB-INF/lib"/>
<!--
    <copy todir="${build.home}/WEB-INF/lib" file="${foo.jar}"/>
-->
 
    <!-- Copy static files from external dependencies as needed -->
    <!-- *** CUSTOMIZE HERE AS REQUIRED BY YOUR APPLICATION *** -->
 
  </target>
 
 
<!-- ==================== Reload Target =================================== -->
 
<!--
 
  The "reload" signals the specified application Tomcat 4 to shut itself down
  and reload. This can be useful when the web application context is not
  reloadable and you have updated classes or property files in the
  /WEB-INF/classes directory or when you have added or updated jar files in the
  /WEB-INF/lib directory.
 
  NOTE: The /WEB-INF/web.xml web application configuration file is not reread
  on a reload. If you have made changes to your web.xml file you must stop
  then start the web application. 
 
-->
 
  <target name="reload" depends="compile"
   description="Reload application on servlet container">
 
    <reload url="${manager.url}"
       username="${manager.username}"
       password="${manager.password}"
           path="${app.path}"/>
 
  </target>
 
 
<!-- ==================== Remove Target =================================== -->
 
<!--
 
  The "remove" target tells the specified Tomcat 4 installation to dynamically
  remove this web application from service.
 
  NOTE:  This is the logical opposite of the "install" target.
 
-->
 
  <target name="remove"
   description="Remove application on servlet container">
 
    <remove url="${manager.url}"
       username="${manager.username}"
       password="${manager.password}"
           path="${app.path}"/>
 
  </target>
 
 
</project>

 

Tomcat Client Deployer

These notes (below) on TCD also from Jakarta at http://tomcat.apache.org/tomcat-5.5-doc/deployer-howto.html  and at http://www.mbaworld.com/docs/deployer-howto.html

 

Finally, deployment of web application may be achieved using the Tomcat Client Deployer. This is a package which can be used to validate, compile, compress to .WAR, and deploy web applications to production or development Tomcat servers. It should be noted that this feature uses the Tomcat Manager and as such the target Tomcat server should be running.

It is assumed the user will be familar with Apache Ant for using the TCD. Apache Ant is a scripted build tool. The TCD comes pre-packaged with a build script to use. Only a modest understanding of Apache Ant is required (installation as listed earlier in this page, and familiarity with using the operating system command shell and configuring environment variables).

The TCD includes Ant tasks, the Jasper page compiler for JSP compilation before deployment, as well as a task which validates the web application Context Descriptor. The validator task (class org.apache.catalina.ant.ValidatorTask) allows only one parameter: the base path of an exploded web application.

The TCD uses an exploded web application as input (see the list of the properties used below). A web application that is programatically deployed with the deployer may include a Context Desciptor in /META-INF/context.xml.

The TCD includes a ready-to-use Ant script, with the following targets:

  • compile (default): Compile and validate the web application. This can be used standalone, and does not need a running Tomcat server. The compiled application will only run on the associated Tomcat 5.5.x server release, and is not guaranteed to work on another Tomcat release, as the code generated by Jasper depends on its runtime component. It should also be noted that this target will also compile automatically any Java source file located in the /WEB-INF/classes folder of the web application.
  • deploy: Deploy a web application (compiled or not) to a Tomcat server.
  • undeploy: Undeploy a web application
  • start: Start web application
  • reload: Reload web application
  • stop: Stop web application

In order for the deployment to be configured, create a file called deployer.properties in the TCD installation directory root. In this file, add the following name=value pairs per line:

Additionally, you will need to ensure that a user has been setup for the target Tomcat Manager (which TCD uses) otherwise the TCD will not authenticate with the Tomcat Manager and the deployment will fail. To do this, see the Tomcat Manager page.

  • build: The build folder used will be, by default, ${build}/webapp/${path}. After the end of the execution of the compile target, the web application .WAR will be located at ${build}/webapp/${path}.war.
  • webapp: The directory containing the exploded web application which will be compiled and validated. By default, the folder is myapp.
  • path: Deployed context path of the web application, by default /myapp.
  • url: Absolute URL to the Tomcat Manager web application of a running Tomcat server, which will be used to deploy and undeploy the web application. By default, the deployer will attempt to access a Tomcat instance running on localhost, at http://localhost:8080/manager.
  • username: Tomcat Manager username (user should have a role of manager)
  • password: Tomcat Manager password.

 

 

 

AddressBook web app

The links for this example are at

http://www.onjava.com/onjava/2003/01/08/examples/Home.html

 

http://www.onjava.com/pub/a/onjava/2003/01/08/tomcat4.html

 

I had to go through and change slashes.

 

The build script:

 

<project name="Web Application" default="build" basedir=".">

<!—Note the inclusion of the build.properties file------------------------------------------------------>

 

    <property file="${user.home}\build.properties"/>

    <property file="build.properties"/>

<!—Note all these Tomcat tasks------------------------------------------------------->

    <taskdef name="deploy"    classname="org.apache.catalina.ant.DeployTask"/>

    <taskdef name="install"   classname="org.apache.catalina.ant.InstallTask"/>

    <taskdef name="list"      classname="org.apache.catalina.ant.ListTask"/>

    <taskdef name="reload"    classname="org.apache.catalina.ant.ReloadTask"/>

    <taskdef name="remove"    classname="org.apache.catalina.ant.RemoveTask"/>

    <taskdef name="resources" classname="org.apache.catalina.ant.ResourcesTask"/>

    <taskdef name="roles"     classname="org.apache.catalina.ant.RolesTask"/>

    <taskdef name="start"     classname="org.apache.catalina.ant.StartTask"/>

    <taskdef name="stop"      classname="org.apache.catalina.ant.StopTask"/>

    <taskdef name="undeploy"  classname="org.apache.catalina.ant.UndeployTask"/>

 

    <path id="classpath">

        <fileset dir="${tomcat.home}\common\lib">

            <include name="*.jar"/>

        </fileset>

        <fileset dir="${tomcat.home}\shared\lib">

            <include name="*.jar"/>

        </fileset>

    </path>

 

    <target name="init">

        <tstamp/>

    </target>

 

    <target name="clean" description="Deletes the Web Application's war directory and war file">

        <echo message="Deleting ${app.name}'s war directory and war file ..."/>

        <delete dir="${basedir}\war"/>

        <delete file="${basedir}\${app.name}.war"/>

    </target>

 

    <target name="prepare" description="Creates the Web Application's war directory" depends="init">

        <echo message="Creating ${app.name}'s war directory ..."/>

        <mkdir dir="${basedir}\war"/>

        <mkdir dir="${basedir}\war\WEB-INF"/>

        <mkdir dir="${basedir}\war\WEB-INF\classes"/>

        <mkdir dir="${basedir}\war\WEB-INF\lib"/>

    </target>

 

    <target name="build" description="Builds the Web Application" depends="prepare">

        <echo message="Building ${app.name} ..."/>

        <javac srcdir="${basedir}\src" destdir="${basedir}\war\WEB-INF\classes">

            <include name="**\*.java"/>

          <!--  <classpath refid="classpath"/>-->

        </javac>

        <copy todir="${basedir}\war\WEB-INF">

            <fileset dir="${basedir}\web\WEB-INF">

                <include name="web.xml"/>

            </fileset>

        </copy>

        <copy todir="${basedir}\war">

            <fileset dir="${basedir}\web">

                <include name="**\*.html"/>

                <include name="**\*.jsp"/>

                <include name="**\*.txt"/>

                <include name="**\*.zip"/>

                <include name="**\*.sit"/>

                <include name="**\*.gif"/>

                <include name="**\*.jpg"/>

                <include name="**\*.png"/>

            </fileset>

        </copy>

        <copy todir="${basedir}\war\META-INF">

            <fileset dir=".">

                <include name="context.xml" />

            </fileset>

        </copy>

    </target>

 

    <target name="package" description="Packages the Web Application's web archive file" depends="build">

        <echo message="Packaging ${app.name}'s war file ..."/>

        <delete file="${basedir}\${app.name}.war"/>

        <jar jarfile="${basedir}\${app.name}.war">

            <fileset dir="${basedir}\war" includes="**"/>

        </jar>

    </target>

 

    <target name="install" description="Installs the Web Application" depends="package">

        <echo message="Installing ${app.name} ..."/>

        <install url="${manager.url}" username="${username}" password="${password}" path="\${app.name}"

            config="file:${basedir}\war\META-INF\context.xml" war="file:${basedir}\${app.name}.war"/>

    </target>

 

    <target name="reload" description="Reloads the Web Application" depends="package">

        <echo message="Reloading ${app.name} ..."/>

        <reload url="${manager.url}" username="${username}" password="${password}" path="\${app.name}"/>

    </target>

 

    <target name="remove" description="Removes the Web Application">

        <echo message="Removing ${app.name} ..."/>

        <remove url="${manager.url}" username="${username}" password="${password}" path="\${app.name}"/>

    </target>

 

    <target name="deploy" description="Deploys the Web Application" depends="package">

        <echo message="Deploying ${app.name} ..."/>

        <deploy url="${manager.url}" username="${username}" password="${password}" path="/${app.name}"

            war="file:${basedir}\${app.name}.war"/>

    </target>

 

    <target name="undeploy" description="Undeploys the Web Application">

        <echo message="Undeploying ${app.name} ..."/>

        <undeploy url="${manager.url}" username="${username}" password="${password}" path="/${app.name}"/>

    </target>

 

    <target name="start" description="Start the Web Application">

        <echo message="Start the Web Application ..."/>

        <start url="${manager.url}" username="${username}" password="${password}" path="\${app.name}"/>

    </target>

 

    <target name="stop" description="Stop the Web Application">

        <echo message="Stop the Web Application ..."/>

        <stop url="${manager.url}" username="${username}" password="${password}" path="\${app.name}"/>

    </target>

 

    <target name="list" description="Lists Installed and Deployed Web Applications">

        <echo message="Listing Installed and Deployed Web Applications ..."/>

        <list url="${manager.url}" username="${username}" password="${password}"/>

    </target>

 

    <target name="resources" description="Lists Tomcat Global Resources of All Types">

        <echo message="Listing Tomcat Global Resources of All Types ..."/>

        <resources url="${manager.url}" username="${username}" password="${password}"/>

    </target>

 

    <target name="roles" description="Lists Tomcat Security Roles">

        <echo message="Listing Tomcat Security Roles ..."/>

        <roles url="${manager.url}" username="${username}" password="${password}"/>

    </target>

 

    <target name="debug">

        <echo message="Lists the properties for debugging purposes ..."/>

        <echo message="app.name    = ${app.name}"/>

        <echo message="basedir     = ${basedir}"/>

        <echo message="user.home   = ${user.home}"/>

        <echo message="tomcat.home = ${tomcat.home}"/>

        <echo message="manager.url = ${manager.url}"/>

        <echo message="username    = ${username}"/>

   <!-- <echo message="password    = ${password}"/> commented out for security reasons -->

   </target>

 

</project>

 

Configuring paths to tomcat and java.  Here is the build.properties file.  Make sure the user/pw are defined. Look in tomcat-users.xml file on your tomcat server.

 

app.name=AddressBook

tomcat.home=C:\tomcat6.018\apache-tomcat-6.0.18

manager.url=http://localhost:8080/manager

username=admin

password=admin

 

 

You’ll need to have both your MySQL db server and Tomcat running.

AddressBook comes with JSP and ant build scripts.  I had to fix the db connection part to get it to connect. 

It comes with CRUD functionality.

Exercise:  Add phone numbers.

 

Exercise.  Mimic the construction here to produce an original webapp using ant build script. 

 

Other sites

 

http://devlibrary.businessobjects.com/BusinessObjectsXI/en/en/RE_SDK/resdk_dg_doc/doc/deploying_web_applications_EN/ewuap026.html

http://www.roseindia.net/jboss/buildingwebapplicationwithant.shtml

 

 

This tutorial is developed from tbe RoseIndia link above.  It develops one Hello World Servlet and a JSP file file to call Hello World Servlet.   J2EE webapps may be deployed as war or ear depending on the conrtainer.  Tomcat accepts war format.  Some containers require ear files.  First of all let's understand the structure of .ear and .war files.

Enterprise Archive Contents

Enterprise Archive (.ear) component follows the standard directory structure defined in the J2EE specification. 

Directory Structure of .ear archive

 /

  .war and .jar files

  Meta-inf

     

  application.xml

   

  

In the .ear file .war,.jar and application.xml file are packaged in the above format.

Enterprise Archive Contents

Web component follows the standard directory structure defined in the J2EE specification. 

Directory Structure of Web Component

 /

   index.htm, JSP, Images etc..

  Web-inf

  

web.xml

  

classes

  

      servlet classes

  

lib

  

      jar files

   

  

Root directory of the web archive ('.war' file) contains all the html, jsp, images files and the additional directories containing these files. In the root directory there is a special directory 'Web-inf' which contains the web deployment descriptor (web.xml), classes and the lib directory.  

Directory Structure of Example2 directory

After understanding the structure of .ear and .war file let's look at the directory structure of example2 directory where we have work to develop the deployable .ear file.

Directory structure:

Description of Directory and its content:

Directory

Description

example2

Base directory which contains build.xml and the .ear file generated by Ant utility will be placed here.

build

Various files generated by Ant utility will be placed in different directories under this directory. 

build/deploymentdesciptors

Web.xml and application.xml files are placed in this directory.

build/ear

Intermediate files for the assembling of example2.ear ear file are placed here.

build/jar

Any jar file if required will be placed in this directory.

build/war

Intermediate files for the assembling of example2.war ear file are placed here.

build/src

All the compiled .class files are placed in this directory.

src

All the java source files are placed here.

web

All the html,jsp, images etc. files are placed in this directory.

In this lesson we creating HelloWorld.java and index.jsp which is in the /src and /web directory respectively.

Source code of HelloWorld.java:

/*

* HelloWorld.java

*

*/

import java.io.*;

import java.text.*;

import java.util.*;

import javax.servlet.*;

import javax.servlet.http.*;

/**

* The Hello World Servelet.

*

* @author Deepak Kumar

* http://www.roseindia.net

* deepak@roseindia.net

*/

public class HelloWorld extends HttpServlet {

public void service(HttpServletRequest request,
HttpServletResponse response) throws  IOException, ServletException{
    response.setContentType("text/html");
    PrintWriter out = response.getWriter();
    out.println("<html>");
    out.println("<head>");
    out.println("<title>Hello World Servlet!</title>");
    out.println("</head>");
    out.println("<body>");
    out.println("<p align=\"center\"><font size=\"5\" color=\"#000080\">Hello World!</font></p>");
    out.println("<p align=\"center\"><a href=\"javascript:history.back()\">Go to Home</a></p>");
    out.println("</body>");
    out.println("</html>");
   }
}
      

Here is the code of index.jsp file:

 <%@page language="java" %>
<html>

<head>
<title>Welcome to Jboss 3.0 tutorial</title>
</head>

<body bgcolor="#FFFFCC">

<p align="center"><font size="6" color="#800000">Welcome to<br>
Jboss 3.0 Tutorial</font></p>
<p align="center"><font color="#000080" size="4">Congralutations you have successfully
installed lesson 2 tutorial</font></p>
<p align="center"><font color="#000080" size="4"><a href="servlet/HelloWorld">Click here
to</a> execute Hello World Servlet.</font></p>
<p><font size="4">&nbsp;</font></p>
<p align="center"><font color="#000080"><font size="4">For more tutorials and examples visit
</font> </font><font size="4"><a href="http://www.rosindia.net"><font color="#000080">http://www.rosindia.net</font></a></font></p>
<p align="center"><font size="4">&nbsp;</font></p>
<p align="center"><font color="#000080">Copyright © 2001 roseindia.net. All
rights reserved.</font></p>

</body>

</html>

    

You can download all the file of this tutorial from here.

Writing Application and Web deployment descriptor

Since in this lesson we are developing one servlet and one jsp files so our deployment descriptor is very simple.

web.xml file:

 
<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
"http://java.sun.com/j2ee/dtds/web-app_2_2.dtd">

<web-app>
<servlet> 
   <servlet-name>HelloWorld</servlet-name> 
    <servlet-class>HelloWorld</servlet-class> 
</servlet> 

<servlet-mapping>
      <url-pattern>/servlet/HelloWorld</url-pattern>
      <servlet-name>HelloWorld</servlet-name>
</servlet-mapping>

</web-app>


    

Note error: swap servlet name and url tags above!!!!

 

application.xml file:

 
<?xml version="1.0" encoding="ISO-8859-1"?>

<application>
<display-name>Example 2 </display-name>
<module>
<web>
<web-uri>example2.war</web-uri>
<context-root>/example2</context-root>
</web>
</module>
</application>

    

Above application.xml file describe the content of example2.ear. Tag <web-uri>example2.war</web-uri> describe the name of web module (i.e.. example2.war) packaged in the archive. The context root of this example2.ear is eample2.

Writing Ant build xml file

To build example2.ear file, I have written build.xml which compiles source code and builds deployable archive file.

build.xml file:

 <?xml version="1.0"?>
<!-- ==================================================== -->
<!-- Build file for our first web application -->
<!-- build.xml, Sunday, July 07, 2002 -->
<!-- Author: Deepak Kumar -->
<!-- Email : deepak@roseindia.net -->
<!-- Url : http://www.roseindia.net -->
<!-- ==================================================== -->


<project name="Jboss 3.0 tutorial series" default="all" basedir=".">


<target name="init">
<property name="dirs.base" value="${basedir}"/>
<property name="classdir" value="${dirs.base}/build/src"/>
<property name="src" value="${dirs.base}/src"/>
<property name="web" value="${dirs.base}/web"/>
<property name="deploymentdescription" value="${dirs.base}/build/deploymentdescriptors"/>

<property name="warFile" value="example2.war"/>
<property name="earFile" value="example2.ear"/>


<property name="earDir" value="${dirs.base}/build/ear"/>
<property name="warDir" value="${dirs.base}/build/war"/>


<!-- Create Web-inf and classes directories -->
<mkdir dir="${warDir}/WEB-INF"/>
<mkdir dir="${warDir}/WEB-INF/classes"/>

<!-- Create Meta-inf and classes directories -->
<mkdir dir="${earDir}/META-INF"/>

</target>

<!-- Main target -->
<target name="all" depends="init,build,buildWar,buildEar"/>


<!-- Compile Java Files and store in /build/src directory -->
<target name="build" >
<javac srcdir="${src}" destdir="${classdir}" debug="true" includes="**/*.java" />
</target>

<!-- Create the War File -->
<target name="buildWar" depends="init">
<copy todir="${warDir}/WEB-INF/classes">
<fileset dir="${classdir}" includes="**/*.class" /> 
</copy>

<copy todir="${warDir}/WEB-INF">
<fileset dir="${deploymentdescription}" includes="web.xml" /> 
</copy>

<copy todir="${warDir}">
<fileset dir="${web}" includes="**/*.*" /> 
</copy>

<!-- Create war file and place in ear directory -->
<jar jarfile="${earDir}/${warFile}" basedir="${warDir}" />


</target>


<!-- Create the War File -->
<target name="buildEar" depends="init">
<copy todir="${earDir}/META-INF">
<fileset dir="${deploymentdescription}" includes="application.xml" /> 
</copy>

<!-- Create ear file and place in ear directory -->
<jar jarfile="${dirs.base}/${earFile}" basedir="${earDir}" />
</target>

</project>

   

Above build.xml file is design to create example2.ear for us in the base directory.

Running Ant utility to build example2.ear

Now it's time to build example2.ear and deploy on the Jboss 3.0 application server.

To execute Ant utility go to c:\anttest\example2 directory and issue ant command. 

Out put of ant command:

C:\anttest\example2>ant
Buildfile: build.xml

init:
[mkdir] Created dir: C:\anttest\example2\build\war\WEB-INF
[mkdir] Created dir: C:\anttest\example2\build\war\WEB-INF\classes
[mkdir] Created dir: C:\anttest\example2\build\ear\META-INF

build:
[javac] Compiling 1 source file to C:\anttest\example2\build\src

buildWar:
[copy] Copying 1 file to C:\anttest\example2\build\war\WEB-INF\classes
[copy] Copying 1 file to C:\anttest\example2\build\war\WEB-INF
[copy] Copying 1 file to C:\anttest\example2\build\war
[jar] Building jar: C:\anttest\example2\build\ear\example2.war

buildEar:
[copy] Copying 1 file to C:\anttest\example2\build\ear\META-INF
[jar] Building jar: C:\anttest\example2\example2.ear

all:

BUILD SUCCESSFUL

Total time: 8 seconds
C:\anttest\example2>|

The above process will create example2.ear in c:\anttest\example2 directory.

Deploying and testing J2EE application

Statrt Jboss 3.0 and copy example2.ear file into the JBOSS_HOME/server/default/deploy directory. Jboss application server automatically deploys the application. Open web browse and type http://localhost:8080/example2 in the web browser. Browse should show the screen something like this: